package com.zhongxiangspace.tools;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * @category 工具类 - 日期实用方法类
 */
public class DateUtil {

    /**
     * @param d
     * @return
     * @category 取得格式化效果的系统日期！ 格式如：yyyy-MM-dd HH:mm:ss
     */
    public final static String getDateTimeToString(Date d) {
        if (d == null)
            return "";
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
                Locale.CHINESE);
        return f.format(d);
    }

    public final static String getDateToString(Date d) {
        if (d == null)
            return "";
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINESE);
        return f.format(d);
    }

    /**
     * @param formate
     * @return
     * @category 取得格式化效果的系统日期！ 格式如：yyyy-MM-dd HH:mm:ss
     */
    public final static String getFormateDate(String formate) {
        SimpleDateFormat f = new SimpleDateFormat(formate, Locale.US);
        return f.format(new Date());
    }

    /**
     * @return
     * @category 获取默认格式的日期和时间.形如：2007-7-8- 12:23:54
     */
    public final static String getDateTime() {
        return getFormateDate("yyyy-MM-dd HH:mm:ss");
    }

    /**
     * @return
     * @category 获取默认格式的日期.形如：2007-7-8
     */
    public final static String getDate() {
        return getFormateDate("yyyy-MM-dd");
    }

    /**
     * @return
     * @category 获取当前的年份
     */
    public final static String getYear() {
        return getFormateDate("yyyy");
    }

    /**
     * @return
     * @category 获取当前的短年份
     */
    public final static String getShortYear() {
        return getFormateDate("yy");
    }

    /**
     * @return
     * @category 获取当前的月份
     */
    public final static String getMonth() {
        return getFormateDate("MM");
    }

    /**
     * @return
     * @category 获取当前的短月份
     */
    public final static String getShortMonth() {
        return getFormateDate("M");
    }

    /**
     * @return
     * @category 获取当前的日期
     */
    public final static String getDay() {
        return getFormateDate("dd");
    }

    /**
     * @return
     * @category 获取当前的短日期
     */
    public final static String getShortDay() {
        return getFormateDate("d");
    }

    /**
     * @return
     * @category 获取默认格式的时间(24小时制).形如：16:23:54
     */
    public final static String getTime() {
        return getFormateDate("HH:mm:ss");
    }

    /**
     * @param dateStr
     * @return
     * @category 判断指定的字符串是否是正确的日期时间字符串. 该方法支持日期或日期时间的判断
     */

    public final static boolean isDate(String dateStr) {
        Date dt = parseSimpleDate(dateStr);
        if (dt != null)
            return true;
        return parseSimpleDateTime(dateStr) != null;

    }

    /**
     * @param pattern
     * @param dateStr
     * @return
     * @category 使用指定的模式来判断字符串是否是日期时间字符串.
     */
    public final static boolean isDate(String pattern, String dateStr) {
        return parseSimpleDT(pattern, dateStr) != null;
    }

    /**
     * @param dateStr
     * @return
     * @category 将指定的日期时间格式的字符串转换成日期对象.
     */
    public final static Date parseDateTime(String dateStr) {
        try {
            return DateFormat.getDateTimeInstance().parse(dateStr);
        } catch (ParseException ex) {
            return null;
        }
    }

    /**
     * @param dateStr
     * @return
     * @category 将指定日期格式的字符串转换成日期对象.
     */
    public final static Date parseDate(String dateStr) {
        try {
            return DateFormat.getDateInstance().parse(dateStr);
        } catch (ParseException ex) {
            return null;
        }
    }

    /**
     * @param dateStr
     * @return
     * @category 使用简单化的方式来解析日期时间格式. 格式：yyyy-MM-dd HH:mm:ss
     */
    public final static Date parseSimpleDateTime(String dateStr) {
        return parseSimpleDT("yyyy-MM-dd HH:mm:ss", dateStr);
    }

    /**
     * @param dateStr
     * @return
     * @category 使用简单化的方式来解析日期时间格式. 格式：yyyy-MM-dd
     */
    public final static Date parseSimpleDate(String dateStr) {
        return parseSimpleDT("yyyy-MM-dd", dateStr);
    }

    /**
     * @param timeStr
     * @return
     * @category 使用简单化的方式来解析日期时间格式. 格式：HH:mm:ss
     */
    public final static Date parseSimpleTime(String timeStr) {
        return parseSimpleDT("HH:mm:ss", timeStr);
    }

    /**
     * @param pattern
     * @param dateStr
     * @return
     * @category 使用指定的模式来解析字符串日期时间.
     */
    public final static Date parseSimpleDT(String pattern, String dateStr) {
        try {
            return new SimpleDateFormat(pattern, Locale.US).parse(dateStr);
        } catch (ParseException ex) {
            return null;
        }
    }

    /**
     * @param date1
     * @param date2
     * @return
     * @category 比较两个日期的大小.返回-1表示date1在date2之前，返回0表示两者相等，返回1 则表示date1在date2之后.
     */
    public final static int compareDate(Date date1, Date date2) {

        if (date1 == null || date2 == null) {
            return 0;
        }

        if (date1.before(date2))
            return -1;
        if (date1.after(date2))
            return 1;
        return 0;
    }

    /**
     * @param date1
     * @param date2
     * @return
     * @category 测试日期date1是否在date2之前.
     */
    public final static boolean isBefore(Date date1, Date date2) {
        if (date1 == null || date2 == null)
            return false;
        return date1.before(date2);
    }

    /**
     * @param date1
     * @return
     * @category 测试日期date1是否在当前时间之前.
     */
    public final static boolean isBeforeNow(Date date1) {
        return isBefore(date1, Calendar.getInstance().getTime());
    }

    /**
     * @param date1
     * @param date2
     * @return
     * @category 测试日期date1是否在date2之后.
     */
    public final static boolean isAfter(Date date1, Date date2) {
        if (date1 == null || date2 == null)
            return false;
        return date1.after(date2);
    }

    /**
     * @param date1
     * @return
     * @category 测试日期date1是否在当前时间之后.
     */
    public final static boolean isAfterNow(Date date1) {
        return isAfter(date1, Calendar.getInstance().getTime());
    }

    /**
     * @param date1
     * @param date2
     * @return
     * @category 测试日期date1和date2是否相等.
     */
    public final static boolean isEquals(Date date1, Date date2) {
        if (date1 == null || date2 == null)
            return false;
        return date1.equals(date2);
    }

    /**
     * @param date1
     * @param date2
     * @return
     * @category 测试日期date1和当前时间是否相等.
     */
    public final static boolean isEqualsNow(Date date1) {
        return isEquals(date1, Calendar.getInstance().getTime());
    }

    /**
     * @param deviation
     * @return
     * @category 获取当前日期时间， 参数表示在此基础上的偏差，参数依次表示年、月、日、时、分、秒。
     * 为正则表示在此日期上加、为负则表示在此日期上减。
     */
    public final static Date getNowDate(int... deviation) {
        return setDate(new Date(), deviation);
    }

    /**
     * @param date
     * @param deviation
     * @return
     * @category 在某一指定的日期基础上进行日期的偏差设置，参数意义同getNowDate
     */
    public final static Date setDate(Date date, int... deviation) {
        Calendar cal = Calendar.getInstance(Locale.US);
        cal.setTime(date);
        if (deviation.length < 1)
            return cal.getTime();
        final int[] filed = {Calendar.YEAR, Calendar.MONTH,
                Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE,
                Calendar.SECOND};
        for (int i = 0; i < deviation.length; i++) {
            cal.add(filed[i], deviation[i]);
        }
        return cal.getTime();
    }

    /**
     * @param dateTime 日期时间字符串,必须包含时间
     * @return String
     * @category 对日期时间字符串的提示字符串生成方法.
     * 该方法主要是对日期时间字符串的提示,类似:1分钟前,1小时前等.对于大于1天的,则会提示 1天前,2天前等等这样的提示.
     * @modify
     */
    public final static String dateTimeTips(Date dt) {
        Calendar cal = Calendar.getInstance(); // 获取当前日期时间
        long times = cal.getTimeInMillis() - dt.getTime(); // 获取时间差
        if (times <= 60 * 1000L)
            return "1 分钟前";
        else if (times <= 60 * 60 * 1000L)
            return (times / (60 * 1000)) + " 分钟前";
        else if (times <= 24 * 60 * 60 * 1000L)
            return (times / (60 * 60 * 1000L)) + " 小时前";
        else if (times <= 7 * 24 * 60 * 60 * 1000L)
            return (times / (24 * 60 * 60 * 1000L)) + " 天前";
        else if (times <= 30 * 24 * 60 * 60 * 1000L)
            return (times / (7 * 24 * 60 * 60 * 1000L)) + " 星期前";
        else if (times <= 12 * 30 * 24 * 60 * 60 * 1000L)
            return (times / (30 * 24 * 60 * 60 * 1000L)) + " 个月前";
        return (times / (12 * 30 * 24 * 60 * 60 * 1000L)) + " 年前";
    }

    public final static String dateTips(String dateStr) {
        Date dt = parseSimpleDate(dateStr);
        if (dt == null)
            return dateStr;
        return dateTimeTips(dt);
    }

    public final static String dateTimeTips(String dateTime) {
        Date dt = parseSimpleDateTime(dateTime); // 转换成日期时间类型
        if (dt == null)
            return dateTime;
        return dateTimeTips(dt);
    }

    /**
     * @param d
     * @return java.sql.Date
     * @category java.util.date转换成java.sql.date, 适合保存数据库
     */
    public static java.sql.Date stringToDate(Date d) {
        java.sql.Date sqlDate = new java.sql.Date(d.getTime());
        return sqlDate;
    }

    /**
     * @param d
     * @return java.sql.Timestamp 2011-01-01 12:52:00
     * @category java.util.date转换成java.sql.Timestamp, 适合保存数据库 带时间格式
     * @author Jason
     */
    public static java.sql.Timestamp stringToDateTime(Date d) {
        java.sql.Timestamp time = new java.sql.Timestamp(d.getTime());
        return time;
    }

    /**
     * @param date
     * @return
     * @category date 2013-3-19 下午03:09:19
     */
    public static Date stirngToDateTime(String date) {
        SimpleDateFormat bartDateFormat = new SimpleDateFormat(
                "yyyy-MM-dd HH:mm:ss");
        Date d = null;
        try {
            d = bartDateFormat.parse(date);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // java.sql.Date sqlDate = new java.sql.Date(d.getTime());
        java.sql.Date sqlDate = new java.sql.Date(d.getTime());
        return sqlDate;
    }

    /**
     * @param date
     * @return java.sql.Date
     * @category String 2010-12-25转换成java.sql.date,适合保存数据库
     */
    public static java.sql.Date stringToDate(String date) {
        SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date d = null;
        try {
            d = bartDateFormat.parse(date);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        java.sql.Date sqlDate = new java.sql.Date(d.getTime());
        return sqlDate;
    }

    /**
     * @param D1 开始日期（日期类型）
     * @param D2 结束日期（日期类型）
     * @return 相差的天数
     * @category 返回2个日期之间相差几个日
     */
    public static int getTowDateDays(Date D1, Date D2) {
        int returnValue = 0;
        long aL = 0, oneday = 3600 * 24 * 1000;
        aL = D2.getTime() - D1.getTime();
        returnValue = Integer.parseInt(aL / oneday + "");
        return returnValue;
    }

    /**
     * @param D1 开始日期（日期类型）
     * @param D2 结束日期（日期类型）
     * @return 相差的天数
     * @category 返回2个日期之间相差几个日
     */
    public static int getTowDateDays(String D1, String D2) {

        Date D11 = stringToDate(D1);
        Date D22 = stringToDate(D2);

        return getTowDateDays(D11, D22);
    }

    /**
     * @param pattern 模式(如yyyy-MM-dd)
     * @param date    java.util.Date对象
     * @return 格式化后的时间字符串
     * @category 格式化时间(日期)
     */
    public static String formatDate(String pattern, Date date) {
        return new SimpleDateFormat(pattern, Locale.US).format(date);
    }

    public static String getLastMonthDay() {
        Calendar cal = Calendar.getInstance();
        Date date = new Date();
        cal.setTime(date);
        int year = 0;
        int month = cal.get(Calendar.MONTH); // 上个月月份
        // int day1 = cal.getActualMinimum(Calendar.DAY_OF_MONTH);//起始天数
        int day = cal.getActualMaximum(Calendar.DAY_OF_MONTH); // 结束天数

        // System.out.println("###last month:" + month);
        if (month == 0) {
            year = cal.get(Calendar.YEAR) - 1;
            month = 12;
        } else {
            year = cal.get(Calendar.YEAR);
        }

        String _month = String.valueOf(month);

        if (_month.length() == 1) {
            _month = "0" + _month;
        }

        String endDay = year + "-" + _month + "-" + day;
        return endDay;
    }

    public static Date addDate(String day, int x) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");// 24小时制
        // SimpleDateFormat format = new
        // SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//12小时制
        Date date = null;
        try {
            date = format.parse(day);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        // if (date == null) return "";
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, x);// 24小时制
        // cal.add(Calendar.HOUR, x);12小时制
        date = cal.getTime();
        cal = null;
        return date;

    }

    public static Date addDateTime(String day, int x) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 24小时制
        // SimpleDateFormat format = new
        // SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//12小时制
        Date date = null;
        try {
            date = format.parse(day);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        // if (date == null) return "";
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, x);// 24小时制
        // cal.add(Calendar.HOUR, x);12小时制
        date = cal.getTime();
        cal = null;
        return date;
    }

    public static String addDateString(String day, int x) {

        return getDateToString(addDate(day, x));
    }

    public static String addDateTimeString(String day, int x) {

        return getDateTimeToString(addDate(day, x));
    }

    public static String getMaxDateTime() {

        return "9999-12-31 23:59:59";
    }

    public static String getMinDateTime() {

        return "1900-01-01 00:00:00";
    }

    public static String getMaxDate() {

        return "9999-12-31";
    }

    public static String getMinDate() {

        return "1900-01-01";
    }

    /**
     * @param startDate
     * @param endDate
     * @param betweenDate
     * @return
     * @category 判断betweenDate是否在开始时间startDate和结束时间endDate的闭区间内
     * @author LEIYINING
     */
    public final static boolean IsBetween(Date startDate, Date endDate,
                                          Date betweenDate) {
        int res1 = compareDate(startDate, betweenDate);
        if (res1 == 1) {
            // startDate > betweenDate
            return false;
        }

        int res2 = compareDate(betweenDate, endDate);
        if (res2 == 1) {
            // betweenDate > endDate
            return false;
        }

        return true;
    }

    /**
     * @param startDate
     * @param endDate
     * @param betweenDate
     * @return
     * @category 判断betweenDate是否在开始时间startDate和结束时间endDate的闭区间内
     * @author LEIYINING
     */
    public final static boolean IsBetween(String startDate, String endDate, String betweenDate) {
        Date startDate1 = parseDate(startDate);
        Date endDate1 = parseDate(endDate);
        Date betweenDate1 = parseDate(betweenDate);

        int res1 = compareDate(startDate1, betweenDate1);
        if (res1 == 1) {
            // startDate > betweenDate
            return false;
        }

        int res2 = compareDate(betweenDate1, endDate1);
        if (res2 == 1) {
            // betweenDate > endDate
            return false;
        }

        return true;
    }

    public static long getMonthDiff(String startDate, String endDate) {
        long monthday;

        try {
            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
            Date startDate1;
            startDate1 = fmt.parse(startDate);
            Calendar starCal = Calendar.getInstance();
            starCal.setTime(startDate1);

            int sYear = starCal.get(Calendar.YEAR);
            int sMonth = starCal.get(Calendar.MONTH);
            int sDay = starCal.get(Calendar.DAY_OF_MONTH);

            Date endDate1 = fmt.parse(endDate);
            Calendar endCal = Calendar.getInstance();
            endCal.setTime(endDate1);
            int eYear = endCal.get(Calendar.YEAR);
            int eMonth = endCal.get(Calendar.MONTH);
            int eDay = endCal.get(Calendar.DAY_OF_MONTH);
            monthday = ((eYear - sYear) * 12 + (eMonth - sMonth));
            // 这里计算零头的情况，根据实际确定是否要加1 还是要减1
            return monthday + 1;

        } catch (ParseException e) {
            // TODO Auto-generated catch block
            return 0;
        }

    }

    public static String getBeforeDay() {
        Calendar calendar = Calendar.getInstance(); //得到日历
        calendar.setTime(new Date());//把当前时间赋给日历
        calendar.add(Calendar.DAY_OF_MONTH, -1);  //设置为前一天
        Date dBefore = calendar.getTime();   //得到前一天的时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //设置时间格式
        String beforeDay = sdf.format(dBefore);    //格式化前一天
        return beforeDay;
    }

    /**
     * @param date_value
     * @category 获得指定日期的年份，例如：2016-04-20，返回值：2016
     */
    public static String getYearByDate(String date_value) {
        return date_value.substring(0, 4);
    }

    /**
     * 计算两个时间相差多少秒
     *
     * @param dateTime1
     * @param dateTime2
     * @return
     */
    public static int getDifferTime(String dateTime1, String dateTime2) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int differ_time = 0;
        try {
            differ_time = (int) (sdf.parse(dateTime2).getTime() - sdf.parse(dateTime1).getTime()) / 1000;
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return Math.abs(differ_time);
    }


    /**
     * @category 获得指定日期的月份，例如：2016-04-20，返回值：4
     */
    public static String getMonthByDate(String date_value) {
        String date_month = date_value.substring(5, 7);
        if ("0".equals(date_month.subSequence(0, 1))) {
            date_month = date_month.substring(1, 2);
        }
        return date_month;
    }

}
